package com.java1234.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.java1234.entity.*;
import com.java1234.service.*;
import com.java1234.util.LogUtil;
import com.java1234.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 论坛帖子管理（前后台）Controller
 */
@RestController
@RequestMapping("/bsns/luntan/posts")
public class LunTanPostController {

    @Autowired
    private LuntanPostService luntanPostService;
    @Autowired
    private LuntancategoryService luntanCategoryService;
    @Autowired
    private LuntanPostCategoryService luntanPostCategoryService;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private LuntanPostUserService luntanPostUserService;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private LogUtil logUtil;
    @Autowired
    private HttpServletRequest request;

    private static final Logger logger = LoggerFactory.getLogger(LunTanPostController.class);

    private static final String POST_VIEWS_KEY = "post:views";
    private static final String POST_LIKES_KEY = "post:likes";
    private static final String COMMENT_LIKES_KEY = "comment:likes";
    private static final String REPLY_LIKES_KEY = "reply:likes";

    /**
     * 帖子分页查询(后台帖子管理)
     */
    @PostMapping("/list")
    public R list(@RequestBody PageBean pageBean) {
        String query = pageBean.getQuery().trim();
        String publisher = pageBean.getPublisher().trim();
        String category = pageBean.getCategory().trim();

        // 构建 Redis 缓存键
        String cacheKey = buildCacheKey("postList", query, publisher, category, pageBean.getPageNum(), pageBean.getPageSize());

        // 尝试从 Redis 缓存中获取数据
        Map<String, Object> cachedResult = (Map<String, Object>) redisTemplate.opsForValue().get(cacheKey);
        if (cachedResult != null) {
            logUtil.logOperation(request, "分页查询帖子列表", "list", pageBean.toString(), "缓存命中");
            return R.ok(cachedResult);
        }

        // 构建查询条件
        QueryWrapper<LuntanPost> postQueryWrapper = buildPostQueryWrapper(query, publisher, category);

        // 分页查询
        Page<LuntanPost> pageResult = luntanPostService.page(new Page<>(pageBean.getPageNum(), pageBean.getPageSize()), postQueryWrapper);
        List<LuntanPost> postList = pageResult.getRecords();

        // 填充发布者和分类信息
        postList.forEach(this::addPublisherAndCategoryInfo);

        // 构建返回结果
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("postList", postList);
        resultMap.put("total", pageResult.getTotal());

        // 缓存结果
        redisTemplate.opsForValue().set(cacheKey, resultMap, 3600, TimeUnit.SECONDS); // 缓存 1 小时
        logUtil.logOperation(request, "分页查询帖子列表", "list", pageBean.toString(), resultMap.toString());
        return R.ok(resultMap);
    }

    /**
     * 构建缓存键
     */
    private String buildCacheKey(String prefix, String query, String publisher, String category, int pageNum, int pageSize) {
        return prefix + ":" + query + ":" + publisher + ":" + category + ":" + pageNum + ":" + pageSize;
    }

    /**
     * 构建帖子查询条件
     */
    private QueryWrapper<LuntanPost> buildPostQueryWrapper(String query, String publisher, String category) {
        QueryWrapper<LuntanPost> queryWrapper = new QueryWrapper<>();
        queryWrapper.isNull("parent_id").eq("is_draft", 0); // 只查询已发布的帖子

        if (StringUtil.isNotEmpty(query)) {
            queryWrapper.like("title", query);
        }
        if (StringUtil.isNotEmpty(publisher)) {
            queryWrapper.eq("publisher", publisher);
        }
        if (StringUtil.isNotEmpty(category)) {
            queryWrapper.eq("category", category);
        }

        return queryWrapper;
    }

    /**
     * 填充发布者和分类信息
     */
    private void addPublisherAndCategoryInfo(LuntanPost post) {
        // 获取发布者名称
        addPublisherName(post);

        // 获取分类名称
        addCategoryNames(post);
    }

    /**
     * 获取发布者名称
     */
    private void addPublisherName(LuntanPost post) {
        QueryWrapper<LuntanPostUser> postUserQueryWrapper = new QueryWrapper<>();
        postUserQueryWrapper.eq("post_id", post.getId());
        LuntanPostUser postUser = luntanPostUserService.getOne(postUserQueryWrapper);
        if (postUser != null) {
            SysUser user = sysUserService.getById(postUser.getUserId());
            if (user != null) {
                post.setPublisherName(user.getUsername());
                post.setPublisherId(user.getId()); // 设置发布者 ID
            }
        }
    }

    /**
     * 获取分类名称
     */
    private void addCategoryNames(LuntanPost post) {
        QueryWrapper<LuntanPostCategory> postCategoryQueryWrapper = new QueryWrapper<>();
        postCategoryQueryWrapper.eq("post_id", post.getId());
        List<LuntanPostCategory> postCategoryList = luntanPostCategoryService.list(postCategoryQueryWrapper);
        if (postCategoryList != null && !postCategoryList.isEmpty()) {
            List<String> categoryNames = postCategoryList.stream()
                    .map(postCategory -> {
                        Luntancategory categoryObj = luntanCategoryService.getById(postCategory.getCategoryId());
                        return categoryObj != null ? categoryObj.getName() : null;
                    })
                    .collect(Collectors.toList());
            post.setCategoryNames(categoryNames);
        }
    }

    /**
     * 更新帖子状态
     */
    @GetMapping("/updateStatus/{id}/status/{status}")
    public R updateStatus(@PathVariable Integer id, @PathVariable String status) {
        LuntanPost post = luntanPostService.getById(id);
        if (post == null) {
            logUtil.logOperation(request, "更新帖子状态", "updateStatus", "id=" + id + ", status=" + status, "帖子不存在");
            return R.error("帖子不存在");
        }

        post.setStatus(status);
        boolean result = luntanPostService.saveOrUpdate(post);
        if (result) {
            clearPostCache(post.getCategoryIds());
            loadAllPosts();
            loadHotPosts();
            logUtil.logOperation(request, "更新帖子状态", "updateStatus", "id=" + id + ", status=" + status, "更新成功");
            return R.ok();
        } else {
            logUtil.logOperation(request, "更新帖子状态", "updateStatus", "id=" + id + ", status=" + status, "更新失败");
            return R.error("更新状态失败");
        }
    }

    /**
     * 删除帖子
     */
    @DeleteMapping("/delete/{id}")
    public ResponseEntity<Boolean> deletePostById(@PathVariable Integer id) {
        LuntanPost post = luntanPostService.getById(id);
        if (post == null) {
            logUtil.logOperation(request, "删除帖子", "deletePostById", "id=" + id, "帖子不存在");
            return new ResponseEntity<>(false, HttpStatus.NOT_FOUND);
        }

        boolean result = luntanPostService.deletePostById(id);
        if (result) {
            clearPostCache(post.getCategoryIds());
            loadAllPosts();
            loadHotPosts();
            logUtil.logOperation(request, "删除帖子", "deletePostById", "id=" + id, "删除成功");
            return new ResponseEntity<>(true, HttpStatus.OK);
        } else {
            logUtil.logOperation(request, "删除帖子", "deletePostById", "id=" + id, "删除失败");
            return new ResponseEntity<>(false, HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    /**
     * 批量删除帖子
     */
    @PostMapping("/delete")
    public R delete(@RequestBody Long[] ids) {
        for (Long id : ids) {
            LuntanPost post = luntanPostService.getById(id);
            if (post != null) {
                luntanPostService.deleteCommentOrReply(post);
                clearPostCache(post.getCategoryIds());
            }
        }
        luntanPostService.removeByIds(Arrays.asList(ids));
        loadAllPosts();
        loadHotPosts();
        logUtil.logOperation(request, "批量删除帖子", "delete", "ids=" + Arrays.toString(ids), "删除成功");
        return R.ok();
    }


    /**
     * 清除帖子缓存
     */
    private void clearPostCache(List<Integer> categoryIds) {
        if (categoryIds != null && !categoryIds.isEmpty()) {
            for (Integer categoryId : categoryIds) {
                Set<String> keys = redisTemplate.keys("postList:*:" + categoryId + "*");
                if (keys != null && !keys.isEmpty()) {
                    redisTemplate.delete(keys);
                }
            }
        }
        redisTemplate.delete(redisTemplate.keys("postList:*"));
        redisTemplate.delete("hotPosts");
    }

    /**
     * 更新帖子信息
     */
    @PutMapping("/update")
    public ResponseEntity<Boolean> updatePost(@Validated @RequestBody LuntanPost post) {
        boolean result = luntanPostService.updatePost(post);
        if (result) {
            clearPostCache(post.getCategoryIds());
            loadAllPosts();
            logUtil.logOperation(request, "更新帖子信息", "updatePost", post.toString(), "更新成功");
            return new ResponseEntity<>(true, HttpStatus.OK);
        } else {
            logUtil.logOperation(request, "更新帖子信息", "updatePost", post.toString(), "更新失败");
            return new ResponseEntity<>(false, HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    /**
     * 查询帖子详情
     */
    @GetMapping("/selectById/{id}")
    public ResponseEntity<LuntanPost> getPostById(@PathVariable Integer id) {
        LuntanPost post = luntanPostService.getById(id);
        if (post != null) {
            addPublisherAndCategoryInfo(post);
            post.setComments(getTotalComments(id));
            logUtil.logOperation(request, "查询帖子详情", "getPostById", "id=" + id, post.toString());
            return new ResponseEntity<>(post, HttpStatus.OK);
        } else {
            logUtil.logOperation(request, "查询帖子详情", "getPostById", "id=" + id, "帖子不存在");
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }
    }

    /**
     * 获取最热帖子
     */
    @GetMapping("/selectHotPosts")
    public R selectHotPosts() {
        String cacheKey = "hotPosts";
        List<LuntanPost> hotPosts = (List<LuntanPost>) redisTemplate.opsForValue().get(cacheKey);

        if (hotPosts == null) {
            QueryWrapper<LuntanPost> queryWrapper = new QueryWrapper<>();
            queryWrapper.isNull("parent_id").eq("status", 0).eq("is_draft", 0).orderByDesc("likes").last("LIMIT 10");
            hotPosts = luntanPostService.list(queryWrapper);

            if (hotPosts != null && !hotPosts.isEmpty()) {
                redisTemplate.opsForValue().set(cacheKey, hotPosts, 1, TimeUnit.HOURS);
            }
        }

        hotPosts.forEach(this::addPublisherAndCategoryInfo);
        logUtil.logOperation(request, "获取最热帖子", "selectHotPosts", "", hotPosts.toString());
        return R.ok().put("data", hotPosts);
    }

    /**
     * 查询所有帖子
     */
    @GetMapping("/selectAll")
    public R selectAll(@RequestParam(required = false) Integer categoryId) {
        String cacheKey = "allPosts:" + (categoryId != null ? categoryId : "all");
        List<LuntanPost> posts = (List<LuntanPost>) redisTemplate.opsForValue().get(cacheKey);

        if (posts == null) {
            QueryWrapper<LuntanPost> queryWrapper = new QueryWrapper<>();
            queryWrapper.isNull("parent_id").eq("status", 0).eq("is_draft", 0);

            if (categoryId != null) {
                QueryWrapper<LuntanPostCategory> postCategoryWrapper = new QueryWrapper<>();
                postCategoryWrapper.eq("category_id", categoryId);
                List<LuntanPostCategory> postCategories = luntanPostCategoryService.list(postCategoryWrapper);
                if (postCategories != null && !postCategories.isEmpty()) {
                    List<Integer> postIdList = postCategories.stream().map(LuntanPostCategory::getPostId).collect(Collectors.toList());
                    queryWrapper.in("id", postIdList);
                } else {
                    logUtil.logOperation(request, "查询所有帖子", "selectAll", "categoryId=" + categoryId, "分类下无帖子");
                    return R.ok().put("data", new ArrayList<>());
                }
            }

            posts = luntanPostService.list(queryWrapper);
            posts.forEach(this::addPublisherAndCategoryInfo);
            redisTemplate.opsForValue().set(cacheKey, posts, 1, TimeUnit.HOURS);
        }
        logUtil.logOperation(request, "查询所有帖子", "selectAll", "categoryId=" + categoryId, posts.toString());
        return R.ok().put("data", posts);
    }

    /**
     * 新增评论
     */
    @PostMapping("/addComment")
    public R addComment(@RequestBody LuntanPost comment) {
        comment.setCreateTime(new Date());
        comment.setIsComment(true);
        comment.setIsReply(false);
        comment.setParentId(comment.getParentId()); // 设置 parentId 为帖子的 ID
        luntanPostService.save(comment);

        savePostUser(comment);
        logUtil.logOperation(request, "新增评论", "addComment", comment.toString(), "评论添加成功");
        return R.ok();
    }

    /**
     * 新增回复
     */
    @PostMapping("/addReply")
    public R addReply(@RequestBody LuntanPost reply) {
        reply.setCreateTime(new Date());
        reply.setIsComment(false);
        reply.setIsReply(true);
        reply.setParentId(reply.getParentId()); // 设置父级评论的 ID
        luntanPostService.save(reply);

        savePostUser(reply);
        logUtil.logOperation(request, "新增回复", "addReply", reply.toString(), "回复添加成功");
        return R.ok();
    }

    /**
     * 保存帖子与用户关联
     */
    private void savePostUser(LuntanPost post) {
        String username = getCurrentUsername();
        if (username != null) {
            SysUser sysUser = sysUserService.getByUsername(username);
            if (sysUser != null) {
                LuntanPostUser postUser = new LuntanPostUser();
                postUser.setPostId(post.getId());
                postUser.setUserId(sysUser.getId());
                luntanPostUserService.save(postUser);
            }
        }
    }

    /**
     * 获取帖子评论及回复
     */
    @GetMapping("/getComments/{postId}")
    public R getComments(@PathVariable Integer postId) {
        // 查询帖子的顶级评论（parentId 是 postId）
        QueryWrapper<LuntanPost> commentQueryWrapper = new QueryWrapper<>();
        commentQueryWrapper.eq("parent_id", postId).eq("is_comment", true).eq("status", 0);
        List<LuntanPost> comments = luntanPostService.list(commentQueryWrapper);

        // 递归获取每个评论的子评论
        for (LuntanPost comment : comments) {
            addPublisherName(comment);
            List<LuntanPost> replies = getReplies(comment.getId());
            comment.setReplies(replies);
        }
        logUtil.logOperation(request, "获取帖子评论及回复", "getComments", "postId=" + postId, comments.toString());

        return R.ok().put("data", comments);
    }

    private List<LuntanPost> getReplies(Integer parentId) {
        QueryWrapper<LuntanPost> replyQueryWrapper = new QueryWrapper<>();
        replyQueryWrapper.eq("parent_id", parentId).eq("status", 0);
        List<LuntanPost> replies = luntanPostService.list(replyQueryWrapper);

        for (LuntanPost reply : replies) {
            addPublisherName(reply);
            // 递归获取子评论
            List<LuntanPost> subReplies = getReplies(reply.getId());
            reply.setReplies(subReplies);
        }

        return replies;
    }

    /**
     * 获取全部评论及回复
     */
    @PostMapping("/getAllComments")
    public R getAllComments(@RequestBody PageBean pageBean) {
        QueryWrapper<LuntanPost> queryWrapper = buildCommentQueryWrapper(pageBean);
        Page<LuntanPost> pageResult = luntanPostService.page(new Page<>(pageBean.getPageNum(), pageBean.getPageSize()), queryWrapper);
        List<LuntanPost> commentsAndReplies = pageResult.getRecords();

        commentsAndReplies.forEach(this::addPublisherNameAndReplies);

        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("commentList", commentsAndReplies);
        resultMap.put("total", pageResult.getTotal());
        logUtil.logOperation(request, "获取全部评论及回复", "getAllComments", pageBean.toString(), resultMap.toString());
        return R.ok(resultMap);
    }

    /**
     * 构建评论查询条件
     */
    private QueryWrapper<LuntanPost> buildCommentQueryWrapper(PageBean pageBean) {
        QueryWrapper<LuntanPost> queryWrapper = new QueryWrapper<>();
        queryWrapper.and(wrapper -> wrapper.eq("is_comment", true).eq("is_reply", false).or().eq("is_comment", false).eq("is_reply", true));

        if (StringUtil.isNotEmpty(pageBean.getContent())) {
            queryWrapper.like("content", pageBean.getContent());
        }
        if (StringUtil.isNotEmpty(pageBean.getPublisher())) {
            QueryWrapper<SysUser> userQueryWrapper = new QueryWrapper<>();
            userQueryWrapper.eq("username", pageBean.getPublisher());
            List<SysUser> userList = sysUserService.list(userQueryWrapper);
            if (!userList.isEmpty()) {
                List<Long> userIdList = userList.stream().map(SysUser::getId).collect(Collectors.toList());
                QueryWrapper<LuntanPostUser> postUserQueryWrapper = new QueryWrapper<>();
                postUserQueryWrapper.in("user_id", userIdList);
                List<LuntanPostUser> postUserList = luntanPostUserService.list(postUserQueryWrapper);
                if (!postUserList.isEmpty()) {
                    List<Integer> postIdList = postUserList.stream().map(LuntanPostUser::getPostId).collect(Collectors.toList());
                    queryWrapper.in("id", postIdList);
                }
            }
        }

        return queryWrapper;
    }

    /**
     * 为评论或回复添加发布者名称和回复信息
     */
    private void addPublisherNameAndReplies(LuntanPost commentOrReply) {
        addPublisherName(commentOrReply);

        if (Boolean.TRUE.equals(commentOrReply.getIsComment()) && Boolean.FALSE.equals(commentOrReply.getIsReply())) {
            List<LuntanPost> replies = getReplies(commentOrReply.getId());
            commentOrReply.setReplies(replies);
        }
    }

    /**
     * 评论点赞
     */
    @PostMapping("/comments/{commentId}/like")
    public R toggleCommentLike(@PathVariable Integer commentId) {
        LuntanPost comment = luntanPostService.getById(commentId);
        if (comment == null) {
            logUtil.logOperation(request, "评论点赞", "toggleCommentLike", "commentId=" + commentId, "评论不存在");
            return R.error(404, "评论不存在");
        }

        // 增加点赞数
        redisTemplate.opsForHash().increment(COMMENT_LIKES_KEY, commentId.toString(), 1);

        // 记录用户点赞状态
        String userLikeKey = "user_like:" + getCurrentUsername() + ":" + commentId;
        redisTemplate.opsForValue().set(userLikeKey, "1");
        logUtil.logOperation(request, "评论点赞", "toggleCommentLike", "commentId=" + commentId, "点赞成功");
        return R.ok("点赞成功");
    }
    /**
     * 评论取消点赞
     */
    @PostMapping("/comments/{commentId}/unlike")
    public R toggleCommentUnlike(@PathVariable Integer commentId) {
        LuntanPost comment = luntanPostService.getById(commentId);
        if (comment == null) {
            logUtil.logOperation(request, "评论取消点赞", "toggleCommentUnlike", "commentId=" + commentId, "评论不存在");
            return R.error(404, "评论不存在");
        }

        // 减少点赞数
        redisTemplate.opsForHash().increment(COMMENT_LIKES_KEY, commentId.toString(), -1);

        // 删除用户点赞状态
        String userLikeKey = "user_like:" + getCurrentUsername() + ":" + commentId;
        redisTemplate.delete(userLikeKey);
        logUtil.logOperation(request, "评论取消点赞", "toggleCommentUnlike", "commentId=" + commentId, "取消点赞成功");

        return R.ok("取消点赞成功");
    }

    /**
     * 回复点赞
     */
    @PostMapping("/replies/{replyId}/like")
    public R toggleReplyLike(@PathVariable Integer replyId) {
        LuntanPost reply = luntanPostService.getById(replyId);
        if (reply == null) {
            logUtil.logOperation(request, "回复点赞", "toggleReplyLike", "replyId=" + replyId, "回复不存在");
            return R.error(404, "回复不存在");
        }

        // 增加点赞数
        redisTemplate.opsForHash().increment(REPLY_LIKES_KEY, replyId.toString(), 1);

        // 记录用户点赞状态
        String userLikeKey = "user_like:" + getCurrentUsername() + ":" + replyId;
        redisTemplate.opsForValue().set(userLikeKey, "1");
        logUtil.logOperation(request, "回复点赞", "toggleReplyLike", "replyId=" + replyId, "点赞成功");

        return R.ok("点赞成功");
    }
    /**
     * 回复取消点赞
     */
    @PostMapping("/replies/{replyId}/unlike")
    public R toggleReplyUnlike(@PathVariable Integer replyId) {
        LuntanPost reply = luntanPostService.getById(replyId);
        if (reply == null) {
            return R.error(404, "回复不存在");
        }

        // 减少点赞数
        redisTemplate.opsForHash().increment(REPLY_LIKES_KEY, replyId.toString(), -1);

        // 删除用户点赞状态
        String userLikeKey = "user_like:" + getCurrentUsername() + ":" + replyId;
        redisTemplate.delete(userLikeKey);

        return R.ok("取消点赞成功");
    }

    /**
     * 定期同步点赞数到数据库
     */
    @Scheduled(fixedRate = 60000) // 每分钟执行一次
    public void syncLikes() {
        syncCommentLikes();
        syncReplyLikes();
    }

    private void syncCommentLikes() {
        syncLikesToDatabase(COMMENT_LIKES_KEY);
    }

    private void syncReplyLikes() {
        syncLikesToDatabase(REPLY_LIKES_KEY);
    }

    /**
     * 同步点赞数到数据库
     */
    private void syncLikesToDatabase(String key) {
        redisTemplate.opsForHash().entries(key).forEach((id, likes) -> {
            LuntanPost post = luntanPostService.getById(Integer.parseInt(id.toString()));
            if (post != null) {
                post.setLikes(Integer.parseInt(likes.toString()));
                luntanPostService.updateById(post);
            }
        });
    }

    /**
     * 增加浏览量
     */
    @PostMapping("/posts/{postId}/view")
    public R incrementViewCount(@PathVariable Integer postId) {
        LuntanPost post = luntanPostService.getById(postId);
        if (post == null) {
            return R.error(404, "帖子不存在");
        }

        luntanPostService.incrementViews(postId);
        redisTemplate.opsForHash().increment(POST_VIEWS_KEY, postId.toString(), 1);
        return R.ok("浏览量增加成功");
    }

    /**
     * 获取评论和回复总数
     */
    private int getTotalComments(Integer postId) {
        QueryWrapper<LuntanPost> commentQueryWrapper = new QueryWrapper<>();
        commentQueryWrapper.eq("parent_id", postId).eq("is_comment", true);
        int commentCount = luntanPostService.count(commentQueryWrapper);

        QueryWrapper<LuntanPost> replyQueryWrapper = new QueryWrapper<>();
        replyQueryWrapper.eq("parent_id", postId).eq("is_reply", true);
        int replyCount = luntanPostService.count(replyQueryWrapper);

        // 递归计算子评论的数量
        replyQueryWrapper.clear();
        replyQueryWrapper.eq("parent_id", postId);
        List<LuntanPost> replies = luntanPostService.list(replyQueryWrapper);
        for (LuntanPost reply : replies) {
            replyCount += getTotalComments(reply.getId());
        }

        return commentCount + replyCount;
    }

    /**
     * 帖子点赞
     */
    @PostMapping("/posts/{postId}/like")
    public R toggleLike(@PathVariable Integer postId) {
        LuntanPost post = luntanPostService.getById(postId);
        if (post == null) {
            logUtil.logOperation(request, "帖子点赞", "toggleLike", "postId=" + postId, "帖子不存在");
            return R.error(404, "帖子不存在");
        }

        redisTemplate.opsForHash().increment(POST_LIKES_KEY, postId.toString(), 1);
        String userLikeKey = "user_like:" + getCurrentUsername() + ":" + postId;
        redisTemplate.opsForValue().set(userLikeKey, "1");
        logUtil.logOperation(request, "帖子点赞", "toggleLike", "postId=" + postId, "点赞成功");
        return R.ok("点赞成功");
    }

    /**
     * 帖子取消点赞
     */
    @PostMapping("/posts/{postId}/unlike")
    public R toggleUnlike(@PathVariable Integer postId) {
        LuntanPost post = luntanPostService.getById(postId);
        if (post == null) {
            return R.error(404, "帖子不存在");
        }

        redisTemplate.opsForHash().increment(POST_LIKES_KEY, postId.toString(), -1);
        String userLikeKey = "user_like:" + getCurrentUsername() + ":" + postId;
        redisTemplate.delete(userLikeKey);
        return R.ok("取消点赞成功");
    }

    /**
     * 初始化 Redis 缓存
     */
    @PostConstruct
    public void initRedisCache() {
        List<LuntanPost> posts = luntanPostService.list();
        for (LuntanPost post : posts) {
            redisTemplate.opsForHash().put(POST_LIKES_KEY, post.getId().toString(), post.getLikes());
            redisTemplate.opsForHash().put(POST_VIEWS_KEY, post.getId().toString(), post.getViews());
        }
    }

    /**
     * 定期同步浏览量和点赞数到数据库
     */
    @Scheduled(fixedRate = 60000) // 每分钟执行一次
    public void syncPostViewsAndLikes() {
        logger.info("Starting syncPostViewsAndLikes task");
        syncPostViews();
        syncPostLikes();
        logger.info("Finished syncPostViewsAndLikes task");
    }

    private void syncPostViews() {
        syncViewsOrLikesToDatabase(POST_VIEWS_KEY, "views");
    }

    private void syncPostLikes() {
        syncViewsOrLikesToDatabase(POST_LIKES_KEY, "likes");
    }

    /**
     * 同步浏览量或点赞数到数据库
     */
    private void syncViewsOrLikesToDatabase(String key, String field) {
        redisTemplate.opsForHash().entries(key).forEach((postId, value) -> {
            LuntanPost post = luntanPostService.getById(Integer.parseInt(postId.toString()));
            if (post != null) {
                if ("views".equals(field)) {
                    post.setViews(Integer.parseInt(value.toString()));
                } else if ("likes".equals(field)) {
                    post.setLikes(Integer.parseInt(value.toString()));
                }
                luntanPostService.updateById(post);
            }
        });
    }

    /**
     * 发布帖子
     */
    @PostMapping("/posts/create")
    public R createPost(@RequestBody LuntanPost post) {
        post.setCreateTime(new Date());
        luntanPostService.save(post);

        savePostUser(post);

        if (post.getCategoryIds() != null && !post.getCategoryIds().isEmpty()) {
            for (Integer categoryId : post.getCategoryIds()) {
                LuntanPostCategory postCategory = new LuntanPostCategory(post.getId(), categoryId);
                luntanPostCategoryService.save(postCategory);
            }
        }

        clearPostCache(post.getCategoryIds());
        loadAllPosts();
        logUtil.logOperation(request, "发布帖子", "createPost", post.toString(), "帖子发布成功");
        return R.ok("帖子发布成功").put("data", post.getId());
    }

    /**
     * 重新加载所有帖子数据
     */
    private void loadAllPosts() {
        QueryWrapper<LuntanPost> queryWrapper = new QueryWrapper<>();
        queryWrapper.isNull("parent_id").eq("status", 0).eq("is_draft", 0);
        List<LuntanPost> posts = luntanPostService.list(queryWrapper);
        posts.forEach(this::addPublisherAndCategoryInfo);
        redisTemplate.opsForValue().set("allPosts:all", posts, 1, TimeUnit.HOURS);
    }
    /**
     * 重新加载最热帖子数据
     */
    private void loadHotPosts() {
        // 重新加载热门帖子数据
        String cacheKey = "hotPosts";
        List<LuntanPost> hotPosts = (List<LuntanPost>) redisTemplate.opsForValue().get(cacheKey);

        if (hotPosts == null) {
            // 查询点赞数最高的前 10 个帖子，且 parent_id 为 null，status 为 0
            QueryWrapper<LuntanPost> postQueryWrapper = new QueryWrapper<>();
            postQueryWrapper.isNull("parent_id").eq("status", 0).eq("is_draft", 0).orderByDesc("likes").last("LIMIT 10");

            hotPosts = luntanPostService.list(postQueryWrapper);

            if (hotPosts != null && !hotPosts.isEmpty()) {
                // 缓存热门帖子列表，设置过期时间为 1 小时
                redisTemplate.opsForValue().set(cacheKey, hotPosts, 1, TimeUnit.HOURS);
            }
        }

        // 为热门帖子填充发布者和分类信息
        hotPosts.forEach(this::addPublisherAndCategoryInfo);
    }

    /**
     * 获取当前登录的用户名
     */
    private String getCurrentUsername() {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if (principal instanceof UserDetails) {
            return ((UserDetails) principal).getUsername();
        } else {
            return principal.toString();
        }
    }

    /**
     * 保存草稿
     */
    @PostMapping("/posts/saveDraft")
    public R saveDraft(@RequestBody LuntanPost post) {
        post.setIsDraft(1);
        post.setCreateTime(new Date());
        luntanPostService.save(post);

        savePostUser(post);

        if (post.getCategoryIds() != null && !post.getCategoryIds().isEmpty()) {
            for (Integer categoryId : post.getCategoryIds()) {
                LuntanPostCategory postCategory = new LuntanPostCategory(post.getId(), categoryId);
                luntanPostCategoryService.save(postCategory);
            }
        }
        logUtil.logOperation(request, "保存草稿", "saveDraft", post.toString(), "草稿保存成功");

        return R.ok("草稿保存成功").put("data", post.getId());
    }

    /**
     * 获取用户草稿
     */
    @GetMapping("/posts/drafts")
    public R getUserDrafts() {
        String username = getCurrentUsername();
        if (username != null) {
            SysUser sysUser = sysUserService.getByUsername(username);
            if (sysUser != null) {
                QueryWrapper<LuntanPostUser> postUserWrapper = new QueryWrapper<>();
                postUserWrapper.eq("user_id", sysUser.getId());
                List<LuntanPostUser> postUserList = luntanPostUserService.list(postUserWrapper);
                if (!postUserList.isEmpty()) {
                    List<Integer> postIdList = postUserList.stream().map(LuntanPostUser::getPostId).collect(Collectors.toList());
                    QueryWrapper<LuntanPost> postWrapper = new QueryWrapper<>();
                    postWrapper.in("id", postIdList).eq("is_draft", 1);
                    List<LuntanPost> drafts = luntanPostService.list(postWrapper);
                    drafts.forEach(this::addPublisherAndCategoryInfo);
                    logUtil.logOperation(request, "获取用户草稿", "getUserDrafts", "username=" + username, drafts.toString());
                    return R.ok().put("data", drafts);
                }
            }
        }
        logUtil.logOperation(request, "获取用户草稿", "getUserDrafts", "username=" + getCurrentUsername(), "无草稿");
        return R.ok().put("data", new ArrayList<>());
    }

    /**
     * 获取草稿详情
     */
    @GetMapping("/posts/drafts/{draftId}")
    public R getDraftDetails(@PathVariable Integer draftId) {
        LuntanPost draft = luntanPostService.getById(draftId);
        if (draft != null) {
            addPublisherAndCategoryInfo(draft);
            return R.ok().put("data", draft);
        } else {
            return R.error("未找到草稿帖子: " + draftId);
        }
    }

    /**
     * 更新草稿信息
     */
    @PutMapping("/updateDraft")
    public ResponseEntity<Map<String, Object>> updateDraft(@Validated @RequestBody LuntanPost post) {
        post.setIsDraft(0);

        if (post.getCategoryIds() == null || !(post.getCategoryIds() instanceof List)) {
            Map<String, Object> errorResponse = new HashMap<>();
            errorResponse.put("success", false);
            errorResponse.put("message", "categoryIds 字段类型不是数组");
            return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
        }

        boolean result = luntanPostService.updatePost(post);
        if (result) {
            clearPostCache(post.getCategoryIds());
            loadAllPosts();
            Map<String, Object> response = new HashMap<>();
            response.put("success", true);
            response.put("data", post.getId());
            logUtil.logOperation(request, "更新草稿信息", "updateDraft", post.toString(), "更新成功");
            return new ResponseEntity<>(response, HttpStatus.OK);
        } else {
            Map<String, Object> errorResponse = new HashMap<>();
            errorResponse.put("success", false);
            errorResponse.put("message", "更新失败");
            logUtil.logOperation(request, "更新草稿信息", "updateDraft", post.toString(), "更新失败");
            return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    /**
     * 获取帖子的点赞数和浏览量
     */
    @GetMapping("/posts/{postId}/stats")
    public R getPostStats(@PathVariable Integer postId) {
        Integer likes = (Integer) redisTemplate.opsForHash().get(POST_LIKES_KEY, postId.toString());
        Integer views = (Integer) redisTemplate.opsForHash().get(POST_VIEWS_KEY, postId.toString());

        Map<String, Object> stats = new HashMap<>();
        stats.put("likes", likes != null ? likes : 0);
        stats.put("views", views != null ? views : 0);
        return R.ok(stats);
    }

    /**
     * 获取评论的点赞数
     */
    @GetMapping("/comments/{commentId}/stats")
    public R getCommentStats(@PathVariable Integer commentId) {
        Integer likes = (Integer) redisTemplate.opsForHash().get(COMMENT_LIKES_KEY, commentId.toString());
        Map<String, Object> stats = new HashMap<>();
        stats.put("likes", likes != null ? likes : 0);
        return R.ok(stats);
    }

    /**
     * 获取回复的点赞数
     */
    @GetMapping("/replies/{replyId}/stats")
    public R getReplyStats(@PathVariable Integer replyId) {
        Integer likes = (Integer) redisTemplate.opsForHash().get(REPLY_LIKES_KEY, replyId.toString());
        Map<String, Object> stats = new HashMap<>();
        stats.put("likes", likes != null ? likes : 0);
        return R.ok(stats);
    }

    /**
     * 查询当前登录用户的帖子
     */
    @GetMapping("/posts/user")
    public R getUserPosts() {
        String username = getCurrentUsername();
        if (username != null) {
            SysUser sysUser = sysUserService.getByUsername(username);
            if (sysUser != null) {
                QueryWrapper<LuntanPostUser> postUserWrapper = new QueryWrapper<>();
                postUserWrapper.eq("user_id", sysUser.getId());
                List<LuntanPostUser> postUserList = luntanPostUserService.list(postUserWrapper);
                if (!postUserList.isEmpty()) {
                    List<Integer> postIdList = postUserList.stream().map(LuntanPostUser::getPostId).collect(Collectors.toList());
                    QueryWrapper<LuntanPost> postWrapper = new QueryWrapper<>();
                    postWrapper.in("id", postIdList).isNull("parent_id").eq("is_draft", 0);
                    List<LuntanPost> userPosts = luntanPostService.list(postWrapper);
                    userPosts.forEach(this::addPublisherAndCategoryInfo);
                    logUtil.logOperation(request, "查询当前登录用户的帖子", "getUserPosts", "username=" + username, userPosts.toString());
                    return R.ok().put("data", userPosts);
                }
            }
        }
        logUtil.logOperation(request, "查询当前登录用户的帖子", "getUserPosts", "username=" + getCurrentUsername(), "无帖子");
        return R.ok().put("data", new ArrayList<>());
    }

    /**
     * 根据用户ID查询用户的帖子，并返回帖子总数、点赞总量和评论总数
     */
    @GetMapping("/posts/user/{userId}")
    public R getUserPostsByUserId(@PathVariable Integer userId) {
        // 检查用户ID是否为空
        if (userId == null) {
            return R.error("用户ID不能为空");
        }

        // 查询用户信息
        SysUser sysUser = sysUserService.getById(userId);
        if (sysUser == null) {
            return R.error("用户不存在");
        }

        // 查询用户发布的帖子
        QueryWrapper<LuntanPostUser> postUserWrapper = new QueryWrapper<>();
        postUserWrapper.eq("user_id", userId);
        List<LuntanPostUser> postUserList = luntanPostUserService.list(postUserWrapper);

        if (!postUserList.isEmpty()) {
            // 获取帖子ID列表
            List<Integer> postIdList = postUserList.stream()
                    .map(LuntanPostUser::getPostId)
                    .collect(Collectors.toList());

            // 查询帖子信息（过滤掉草稿帖子）
            QueryWrapper<LuntanPost> postWrapper = new QueryWrapper<>();
            postWrapper.in("id", postIdList)
                    .isNull("parent_id") // 过滤掉回复帖子
                    .eq("is_draft", 0); // 过滤掉草稿帖子

            List<LuntanPost> userPosts = luntanPostService.list(postWrapper);

            // 计算帖子总数
            int postCount = userPosts.size();

            // 计算点赞总量
            int likeCount = userPosts.stream()
                    .mapToInt(LuntanPost::getLikes)
                    .sum();

            // 计算评论总数（用户发布的帖子下的所有评论）
            int commentCount = 0;
            for (LuntanPost post : userPosts) {
                // 查询每个帖子下的评论数量
                QueryWrapper<LuntanPost> commentWrapper = new QueryWrapper<>();
                commentWrapper.eq("parent_id", post.getId()); // 查询该帖子下的所有评论
                int postCommentCount = luntanPostService.count(commentWrapper);
                commentCount += postCommentCount;
            }

            // 为每个帖子添加发布者和分类信息
            userPosts.forEach(this::addPublisherAndCategoryInfo);

            // 记录日志
            logUtil.logOperation(request, "根据用户ID查询帖子", "getUserPostsByUserId", "userId=" + userId, userPosts.toString());

            // 返回帖子列表及统计信息
            Map<String, Object> result = new HashMap<>();
            result.put("posts", userPosts);
            result.put("postCount", postCount);
            result.put("likeCount", likeCount);
            result.put("commentCount", commentCount);

            return R.ok().put("data", result);
        }

        // 记录日志
        logUtil.logOperation(request, "根据用户ID查询帖子", "getUserPostsByUserId", "userId=" + userId, "无帖子");

        // 返回空列表及统计信息
        Map<String, Object> result = new HashMap<>();
        result.put("posts", new ArrayList<>());
        result.put("postCount", 0);
        result.put("likeCount", 0);
        result.put("commentCount", 0);

        return R.ok().put("data", result);
    }

    /**
     * 查询当前登录用户的评论
     */
    @GetMapping("/comments/user")
    public R getUserComments() {
        String username = getCurrentUsername();
        if (username != null) {
            SysUser sysUser = sysUserService.getByUsername(username);
            if (sysUser != null) {
                List<LuntanPost> userCommentsAndReplies = new ArrayList<>();

                QueryWrapper<LuntanPostUser> commentUserWrapper = new QueryWrapper<>();
                commentUserWrapper.eq("user_id", sysUser.getId());
                List<LuntanPostUser> commentUserList = luntanPostUserService.list(commentUserWrapper);
                if (!commentUserList.isEmpty()) {
                    List<Integer> commentIdList = commentUserList.stream().map(LuntanPostUser::getPostId).collect(Collectors.toList());
                    QueryWrapper<LuntanPost> commentWrapper = new QueryWrapper<>();
                    commentWrapper.in("id", commentIdList).eq("is_comment", 1).eq("is_reply", 0);
                    List<LuntanPost> comments = luntanPostService.list(commentWrapper);
                    userCommentsAndReplies.addAll(comments);
                }

                QueryWrapper<LuntanPostUser> replyUserWrapper = new QueryWrapper<>();
                replyUserWrapper.eq("user_id", sysUser.getId());
                List<LuntanPostUser> replyUserList = luntanPostUserService.list(replyUserWrapper);
                if (!replyUserList.isEmpty()) {
                    List<Integer> replyIdList = replyUserList.stream().map(LuntanPostUser::getPostId).collect(Collectors.toList());
                    QueryWrapper<LuntanPost> replyWrapper = new QueryWrapper<>();
                    replyWrapper.in("id", replyIdList).eq("is_reply", 1).eq("is_comment", 0);
                    List<LuntanPost> replies = luntanPostService.list(replyWrapper);
                    userCommentsAndReplies.addAll(replies);
                }

                userCommentsAndReplies.forEach(this::addPublisherNameAndReplies);
                logUtil.logOperation(request, "查询当前登录用户的评论", "getUserComments", "username=" + username, userCommentsAndReplies.toString());
                return R.ok().put("data", userCommentsAndReplies);
            }
        }
        logUtil.logOperation(request, "查询当前登录用户的评论", "getUserComments", "username=" + getCurrentUsername(), "无评论");
        return R.ok().put("data", new ArrayList<>());
    }
}